package com.guodidi.media.util;

import com.guodidi.media.domain.bo.CustomFile;
import com.guodidi.media.domain.enums.TraverTypeE;
import com.guodidi.media.file.CustomFileVisitor;
import com.guodidi.media.file.CustomVisitResult;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

/**
 * Created by 郭垚辉 on 2017/7/21.
 */
public class FileUtils {


    /**
     * 遍历path路径下的所有文件的路径名称
     *
     * @param path 需要遍历的目录(同时也会遍历该目录下的的隐藏文件)
     * @return 遍历目录下所有的文件
     */
    public static List<Path> traverseDirectory(Path path, TraverTypeE type) {
        if (!Files.exists(path)) {
            System.out.println("需要遍历的文件夹不存在，请确认");
            return null;
        }
        if (Files.exists(path) && !Files.isDirectory(path)) {
            System.out.println("需要的遍历的是文件夹不是文件，请重新选择");
            return null;
        }
        List<Path> pathList = new ArrayList<>();
        CustomVisitResult result = CustomVisitResult.getResult(type);
        try {
            Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), result.getMaxDepth(), new CustomFileVisitor(pathList, result));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pathList;
    }

    public static boolean moveFiles(List<Path> sourcesList, Path destPath) throws IOException {
        if (sourcesList != null && sourcesList.size() < 1) {
            System.out.println("什么东西都没有，无法比对");
            return false;
        }
        Path anyPath = sourcesList.get(0);
        for (Path sourcePath : sourcesList) {
            FileUtils.moveFile(sourcePath, destPath, false);
        }
        return true;
    }


    /**
     * 1. 确认源文件是否存在 2. 检查是否都有源path和目标path是不是文件 3. 如果是单个文件可以这么检查，如果是文件夹间的移动，则不适合
     */
    public static boolean checkFile(Path sourcePath, Path destPath) throws IOException {
        if (!Files.exists(sourcePath)) {
            System.out.println("源文件不存在，请确认!");
            return false;
        }
        if (!Files.exists(destPath)) {
            Files.createDirectories(destPath.getParent());
            System.out.println("目标文件所在的文件夹不存在，已为您创建目标文件所在的文件夹");
        }
        if (!Files.isRegularFile(sourcePath)) {
            System.out.println("源path必须是文件！");
            return false;
        }
        if (Files.exists(destPath) && !Files.isRegularFile(destPath)) {
            System.out.println("目标path必须是文件！");
            return false;
        }
        return true;
    }


    /**
     * @param sourcePath 必须是文件
     * @param destPath   必须是文件
     * @Description 将sourcePath拷贝到destPath上。 如果设置了覆盖，则直接覆盖掉同名的目标文件 如果没有设置覆盖，出现同名时，按照windows的命名规则，对文件名进行命名
     */
    public static boolean moveFile(Path sourcePath, Path destPath, boolean isOverride) throws IOException {

        if (!FileUtils.checkFile(sourcePath, destPath)) {
            return false;
        }

        // 不进行覆盖，且存在同名文件，则创建文件，创建规则同windows
        if (!isOverride && Files.exists(destPath)) {
            CustomFile customFile = CustomFile.getFile(destPath);
            // 在文件已经存在的情况下，首先判断其是否有副本 - 仅在win下
            DirectoryStream<Path> duplicationPaths = Files.newDirectoryStream(destPath.getParent(),
                    customFile.getFileName() + Constant.WIN_DUPLICATION + "*" + customFile.getExtName());
            int duplicationNum = 1;
            StringBuffer buffer = new StringBuffer("");
            for (Path path : duplicationPaths) {
                System.out.println(path);
                ++duplicationNum;
            }

            // 创建重命名后的文件
            buffer.append(destPath.getParent() + File.separator);
            buffer.append(customFile.getFileName());
            if (duplicationNum == 1) {
                buffer.append(Constant.WIN_DUPLICATION);
            } else {
                buffer.append(Constant.WIN_BUILD_DUP_LF + duplicationNum + Constant.WIN_BUILD_DUP_RT);
            }
            buffer.append(customFile.getExtName());

            // 新的文件对应的path
            Path newPath = Paths.get(buffer.toString());
            Files.move(sourcePath, newPath);
        } else {
            // 要进行覆盖的话，如果文件存在则先删除文件，再进行移动
            if (Files.exists(destPath)) {
                Files.delete(destPath);
            }
            Files.move(sourcePath, destPath);
        }
        return true;
    }
}
